// 所有实例变量都会生成一个隐式的getter方法。非final类型的实例变量还会生成一个隐式的setter方法
import 'dart:math';

class DartClass {
  late final num x;
  late num y;
  num z = 7; // 直接初始化实例变量
}

// 常量构造器 ，使用const来定义构造器，并且确保所有的实例变量都用final修饰。
class ImmutablePoint {
  static final ImmutablePoint origin = const ImmutablePoint(0, 0);

  final num x, y;

  const ImmutablePoint(this.x, this.y);

  //  var a = const ImmutablePoint(1, 1);
  //   var b = const ImmutablePoint(1, 1);
  //   print(a == b);  true
}

// a.runtimeType  获取变量类型
// 省略const关键字
const pointAndLine = {
  'point': [ImmutablePoint(0, 0)],
  'line': [ImmutablePoint(1, 10), ImmutablePoint(-2, 11)],
};

// 可以通过get和set关键字去重写属性默认的getters和setters方法
class Rectangle {
  // late 解决非空安全
  late num left, top, width, height;
  // 构造器  不会被继承
  Rectangle(num left, num top, num width, num height) {
    this.left = left;
    this.top = top;
    this.width = width;
    this.height = height;
  }
  // 语法糖
  // Rectangle(this.left, this.top, this.width, this.height);

  // Define two calculated properties: right and bottom.
  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
  //  var a = Rectangle(10, 20, 30, 40);
  //   print(a.right);
  //   a.right = 50;
  //   print(a.right);
}

//命名构造器
class Point {
  late num x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
  // Initializer list sets instance variables before
// the constructor body runs.
  Point.fromJson(Map<String, num> json)
      : x = 3,
        y = 4 {
    print(24);
  }
}

class Person {
  late String firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }
}

//父类构造器的参数(参数可以是表达式)是在子类构造器调用之前被赋值的
//那你必须手工调用父类的某个构造器。指定父类构造器是在冒号":"后面，构造器的方法体前面（如果有的话）
class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) {
    print('in Employee');
  }
  //  var emp = new Employee.fromJson({});
  //   // print(object)
  //   if (emp is Person) {
  //     // Type check
  //     emp.firstName = 'Bob';
  //   }
  //   print(emp.firstName);
}

class Point2 {
  final num x;
  final num y;
  final num distanceFromOrigin;

  Point2(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

//重定向构造器——Redirecting constructors
class Point3 {
  num x, y;

  // The main constructor for this class.
  Point3(this.x, this.y);

  // Delegates to the main constructor.
  Point3.alongXAxis(num x) : this(x, 0);
}

// 工厂构造器——Factory constructors
// 使用factory关键字来修饰构造器，不一定每次都会生成新的类的实例。
// 比如，工厂构造器可能会返回缓存中的某个实例，或者它返回子类的一个实例。
class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map<String, Logger> _cache = <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name] as Logger;
    } else {
      final logger = Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) print(msg);
  }

  //  var logger = Logger('UI');
  //   logger.log('Button clicked');
}

// 每个类的内部都隐式的定义了一个接口，这个接口包含类的成员的所有实例，以及类实现的所有接口。
// A person. The implicit interface contains greet().
class Person3 {
  // In the interface, but visible only in this library.
  final _name;

  // Not in the interface, since this is a constructor.
  Person3(this._name);

  // In the interface.
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// An implementation of the Person interface.
class Impostor implements Person3 {
  get _name => '';

  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person3 person3) => person3.greet('Bob');

//可重写的操作符——Overridable operators
class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
  // Operator == and hashCode not shown. For details, see note below.
  // ···
}

// void main() {
//   final v = Vector(2, 3);
//   final w = Vector(2, 2);

//   assert(v + w == Vector(4, 5));
//   assert(v - w == Vector(0, 1));
// }

// 枚举类型

enum Color { red, green, blue }
List<Color> colors = Color.values; //[Color.red, Color.green, Color.blue]

// 通过 width 实现多继承
// class Musician extends Performer with Musical {
//   // ···
// }

//如果你不想让mixin类可以当做普通class一样使用的话，就是用mixin关键字替换class关键字
//使用on关键字可以指定mixin的父类，
mixin Musician {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}

mixin MusicalPerformer on Musician {
  // ···
}

// 定义抽象类 不可以被实例化，但是可以被调用
abstract class AbstractPerson {
  final String? nu;
  AbstractPerson({this.nu});

  // 抽象类中可以定义没有方法体的方法
  void log();

  // 抽象类中可以包含有方法体的方法
  void log2() {
    print("AbstractPerson");
  }
}

// 继承抽象类 , 必须实现抽象类中的抽象方法
class Student3 extends AbstractPerson {
  Student3(String name) : super(nu: name);

  @override
  void log() {
    print("Student3");
  }
}

void main(List<String> args) {
  var temp = Student3('woshi');
  temp.log2();
  print(temp.nu);
}
